package cn.iocoder.yudao.module.vos.service.datamatchtask;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import cn.iocoder.yudao.module.infra.api.file.FileApi;
import cn.iocoder.yudao.module.vos.utils.CdrUtil;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import lombok.extern.slf4j.Slf4j;
import org.bson.Document;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

import cn.iocoder.yudao.module.vos.controller.admin.datamatchtask.vo.*;
import cn.iocoder.yudao.module.vos.dal.dataobject.datamatchtask.DataMatchTaskDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;

import cn.iocoder.yudao.module.vos.dal.mysql.datamatchtask.DataMatchTaskMapper;
import org.springframework.web.multipart.MultipartFile;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.diffList;
import static cn.iocoder.yudao.module.vos.enums.ErrorCodeConstants.*;

/**
 * 数据匹配下载 Service 实现类
 *
 * @author shijun
 */
@Service
@Slf4j
@Validated
public class DataMatchTaskServiceImpl implements DataMatchTaskService {

    @Resource
    private DataMatchTaskMapper dataMatchTaskMapper;

    @Autowired
    private MongoTemplate mongoTemplate;

    @Resource
    private FileApi fileApi;

    @Override
    public Long createDataMatchTask(MultipartFile file, DataMatchTaskSaveReqVO createReqVO) throws IOException {
        // 1. 保存文件到临时目录
        File tempFile = File.createTempFile("upload_" + RandomUtil.randomString(6), ".xlsx");
        file.transferTo(tempFile);
        // 2. 使用 Hutool 读取第一列，跳过标题行
        ExcelReader reader = ExcelUtil.getReader(tempFile);
        List<Object> rawList = reader.readColumn(0, 1); // 第一列，从第1行开始（跳过标题）
        List<String> phoneList = rawList.stream().filter(Objects::nonNull).map(Object::toString).collect(Collectors.toList());
        reader.close();// 第一列，从第1行开始（跳过标题）
        // 3. 删除临时文件
        FileUtil.del(tempFile);

        if (createReqVO.getRetrievalDays() == null) {
            throw exception(RETRIEVAL_DAYS_PARAM_NOT_NULL);
        }
        DataMatchTaskDO dataMatchTaskDO = BeanUtils.toBean(createReqVO, DataMatchTaskDO.class);
        dataMatchTaskDO.setTaskStatus("downloading");
        dataMatchTaskMapper.insert(dataMatchTaskDO);
        CompletableFuture.runAsync(() -> {
            try (ExcelWriter writer = ExcelUtil.getWriter(true); ByteArrayOutputStream out = new ByteArrayOutputStream()) {
                List<Map<String, Object>> dataList = new ArrayList<>();
                Set<String> distinctPhones = new HashSet<>(phoneList);
                MongoCollection<Document> collection = mongoTemplate.getDb().getCollection("cdr");
                // 日期范围
                int retrievalDays = createReqVO.getRetrievalDays();
                LocalDate today = LocalDate.now();
                LocalDate fromDate = today.minusDays(retrievalDays - 1); // 包含今天，比如60天，取今天和前59天
                for (String phone : distinctPhones) {
                    String phoneLast10 = null;
                    Document query = null;
                    if ("phone_md5".equals(createReqVO.getMatchType())) {
                        query = new Document("phone_md5", phone);
                    } else if ("phone_63md5".equals(createReqVO.getMatchType())) {
                        query = new Document("phone_md5+63", phone);
                    } else {
                        phoneLast10 = CdrUtil.trimNumber(phone);
                        query = new Document("_id", phoneLast10);
                    }
                    FindIterable<Document> documents = collection.find(query);
                    for (Document doc : documents) {
                        Map<String, Document> records = (Map<String, Document>) doc.get("records");
                        for (Map.Entry<String, Document> entry : records.entrySet()) {
                            String key = entry.getKey(); // yyyyMMdd
                            LocalDate recordDate;
                            try {
                                recordDate = LocalDate.parse(key, DateTimeFormatter.ofPattern("yyyyMMdd"));
                            } catch (Exception e) {
                                log.warn("Invalid date format for key: {}", key);
                                continue;
                            }
                            // 判断key日期是否在指定范围内
                            if (recordDate.isBefore(fromDate) || recordDate.isAfter(today)) {
                                continue; // 跳过不在范围内的
                            }
                            List<Document> value = (List<Document>) entry.getValue();
                            for (Document detail : value) {
                                Map<String, Object> row = new LinkedHashMap<>();
                                row.put("phone", phone);
                                row.put("callergatewayid", detail.getString("callergatewayid"));
                                row.put("calleetogatewaye164", detail.getString("calleetogatewaye164"));
                                row.put("calleeaccesse164", detail.getString("calleeaccesse164"));
                                row.put("starttime", detail.getLong("starttime") != null ? CdrUtil.dateConvert(detail.getLong("starttime")) : "");
                                row.put("stoptime", detail.getLong("stoptime") != null ? CdrUtil.dateConvert(detail.getLong("stoptime")) : "");
                                row.put("holdtime", detail.getInteger("holdtime"));
                                row.put("enddirection", detail.getInteger("enddirection"));
                                dataList.add(row);
                            }
                        }
                    }
                    log.info("Processed: phone:{}", phone);
                }
                writer.write(dataList, true);
                writer.flush(out, true);
                byte[] content = out.toByteArray();
                String fileName = "batch_" + dataMatchTaskDO.getId() + ".xlsx";
                String url = fileApi.createFile(content, fileName);
                dataMatchTaskDO.setDownloadUrl(url);
                dataMatchTaskDO.setTaskStatus("downloaded");
                dataMatchTaskMapper.updateById(dataMatchTaskDO);

            } catch (Exception e) {
                log.error("Error creating batch download", e);
                dataMatchTaskDO.setTaskStatus("download_failed");
                dataMatchTaskMapper.updateById(dataMatchTaskDO);
            }
        }, ThreadUtil.newExecutor());
        // 返回
        return dataMatchTaskDO.getId();
    }

    @Override
    public void updateDataMatchTask(DataMatchTaskSaveReqVO updateReqVO) {
        // 校验存在
        validateDataMatchTaskExists(updateReqVO.getId());
        // 更新
        DataMatchTaskDO updateObj = BeanUtils.toBean(updateReqVO, DataMatchTaskDO.class);
        dataMatchTaskMapper.updateById(updateObj);
    }

    @Override
    public void deleteDataMatchTask(Long id) {
        // 校验存在
        validateDataMatchTaskExists(id);
        // 删除
        dataMatchTaskMapper.deleteById(id);
    }

    @Override
    public void deleteDataMatchTaskListByIds(List<Long> ids) {
        // 删除
        dataMatchTaskMapper.deleteByIds(ids);
    }


    private void validateDataMatchTaskExists(Long id) {
        if (dataMatchTaskMapper.selectById(id) == null) {
            throw exception(DATA_MATCH_TASK_NOT_EXISTS);
        }
    }

    @Override
    public DataMatchTaskDO getDataMatchTask(Long id) {
        return dataMatchTaskMapper.selectById(id);
    }

    @Override
    public PageResult<DataMatchTaskDO> getDataMatchTaskPage(DataMatchTaskPageReqVO pageReqVO) {
        return dataMatchTaskMapper.selectPage(pageReqVO);
    }

}